# pyinstaller -F heic_to_jpg_converter_gui.py
# xiaoyf 编写

import wx
import os
import pillow_heif
from PIL import Image
from pathlib import Path
#import pyheif


class HeicToJpgConverter(wx.Frame):
    def __init__(self, *args, **kw):
        super(HeicToJpgConverter, self).__init__(*args, **kw)

        self.InitUI()

    def InitUI(self):
        panel = wx.Panel(self)
        vbox = wx.BoxSizer(wx.VERTICAL)

        hbox1 = wx.BoxSizer(wx.HORIZONTAL)
        self.source_entry = wx.TextCtrl(panel)
        hbox1.Add(self.source_entry, proportion=1, flag=wx.EXPAND | wx.RIGHT, border=5)
        self.source_btn = wx.Button(panel, label="选择源文件")
        self.source_btn.Bind(wx.EVT_BUTTON, self.onSelectSource)
        hbox1.Add(self.source_btn, flag=wx.RIGHT, border=5)

        self.dir_button = wx.Button(panel, label="选择目录", pos=(10, 50))
        self.dir_button.Bind(wx.EVT_BUTTON, self.on_open_dir)
        hbox1.Add(self.dir_button, flag=wx.RIGHT, border=5)

        hbox2 = wx.BoxSizer(wx.HORIZONTAL)
        self.target_entry = wx.TextCtrl(panel)
        hbox2.Add(self.target_entry, proportion=1, flag=wx.EXPAND | wx.RIGHT, border=5)
        self.target_btn = wx.Button(panel, label="选择保存目录")
        self.target_btn.Bind(wx.EVT_BUTTON, self.onSelectTarget)
        hbox2.Add(self.target_btn, flag=wx.RIGHT, border=5)

        hbox3 = wx.BoxSizer(wx.HORIZONTAL)
        self.convert_btn = wx.Button(panel, label="提交")
        self.convert_btn.Bind(wx.EVT_BUTTON, self.onConvert)
        hbox3.Add(self.convert_btn, flag=wx.RIGHT, border=5)

        self.exit_btn = wx.Button(panel, label="退出")
        self.exit_btn.Bind(wx.EVT_BUTTON, self.onExit)
        hbox3.Add(self.exit_btn, flag=wx.RIGHT, border=5)

        vbox.Add(hbox1, flag=wx.EXPAND | wx.ALL, border=10)
        vbox.Add(hbox2, flag=wx.EXPAND | wx.ALL, border=10)
        vbox.Add(hbox3, flag=wx.EXPAND | wx.ALL, border=10)

        panel.SetSizer(vbox)

        self.SetSize((600, 200))
        self.SetTitle('HEIC到JPG转换器')
        self.Centre()

    def onSelectSource(self, event):
        dialog = wx.FileDialog(self, "选择源文件", wildcard="HEIC files (*.heic;*.hif)|*.heic;*.hif",
                               style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST)
        if dialog.ShowModal() == wx.ID_CANCEL:
            return
        self.source_entry.SetValue(dialog.GetPath())
        dialog.Destroy()

    def on_open_dir(self, event):
        # 创建目录对话框
        dialog = wx.DirDialog(self, "选择源目录")
        if dialog.ShowModal() == wx.ID_OK:
            path = dialog.GetPath()
            # wx.MessageBox(f"您选择的目录是: {path}")
            self.source_entry.SetValue(path)
        dialog.Destroy()

    def onSelectTarget(self, event):
        dialog = wx.DirDialog(self, "选择保存目录")
        if dialog.ShowModal() == wx.ID_CANCEL:
            return
        self.target_entry.SetValue(dialog.GetPath())
        dialog.Destroy()

    def onConvert(self, event):
        source_path = self.source_entry.GetValue()
        target_path = self.target_entry.GetValue()

        if not source_path:
            wx.MessageBox("请选择源文件", "错误", wx.OK | wx.ICON_ERROR)
            return

        if not target_path:
            wx.MessageBox("请选择保存目录", "错误", wx.OK | wx.ICON_ERROR)
            return
        elif not os.path.isdir(target_path):
            wx.MessageBox("选择的不是一个目录", "错误", wx.OK | wx.ICON_ERROR)
            return

        #if not target_path:
        #    target_path = os.path.dirname(source_path)

        if os.path.isdir(source_path):
            # print(f"{source_path} 是一个目录")
            # 批量转换目录
            self.batch_convert_directory(str(source_path), target_path)
        elif os.path.isfile(source_path):
            #print(f"{source_path} 是一个文件")
            # 转换单个文件
            file_name_with_extension = os.path.basename(source_path)
            file_name_without_extension = os.path.splitext(file_name_with_extension)[0]
            dfilepath = target_path + '/' + file_name_without_extension + '.jpg'
            #print(f"{source_path} ##-> {dfilepath}")
            self.convert_heic_to_jpg(str(source_path), dfilepath)
        else:
            print(f"错误：{source_path} 不是有效的文件或目录")

        #self.convert_file(source_path, target_path)
        wx.MessageBox("操作完成", "信息", wx.OK | wx.ICON_INFORMATION)

    def convert_file(self, file_path, target_path):
        heif_file = pillow_heif.read(file_path)
        image = Image.frombytes(
            heif_file.mode,
            heif_file.size,
            heif_file.data,
            "raw",
            heif_file.mode,
            heif_file.stride,
        )
        output_path = os.path.join(target_path, os.path.splitext(os.path.basename(file_path))[0] + ".jpg")
        image.save(output_path, format="JPEG")

    def onExit(self, event):
        self.Close()


    def convert_heic_to_jpg(self,input_path, output_path=None):
        """
        将单个HEIC文件转换为JPG格式

        Args:
            input_path: HEIC文件的路径
            output_path: 输出JPG文件的路径（可选）

        Returns:
            输出文件的路径
        """
        try:
            # 如果未指定输出路径，则使用输入文件名（改扩展名为.jpg）
            if output_path is None:
                output_path = str(Path(input_path).with_suffix('.jpg'))

            # 读取HEIC文件
            #heif_file = pillow_heif.read_heif(input_path)

            # 打开 HEIC 文件
            heic_image = pillow_heif.open_heif(input_path)

            # 获取 EXIF 信息
            exif_data = heic_image.info.get('exif', b'')

            # 转换为PIL Image
            #image = Image.frombytes(
            #    heif_file.mode,
            #    heif_file.size,
            #    heif_file.data,
            #    "raw",
            #    heif_file.mode,
            #    heif_file.stride,
            #)


            # 将 HEIC 图像转换为 RGB 模式
            rgb_image = Image.frombytes(
                heic_image.mode,
                heic_image.size,
                heic_image.data,
                "raw",
                heic_image.mode,
                heic_image.stride,
            )

            # 保存为JPG
            #image.save(output_path, 'JPEG', quality=95)

            # 保存JPEG文件并尝试保留EXIF信息
            if exif_data:
                rgb_image.save(output_path, format="JPEG", quality=95 , exif=exif_data)
            else:
                rgb_image.save(output_path, format="JPEG", quality=95)

            print(f"转换成功: {input_path} -> {output_path}")
            return output_path

        except Exception as e:
            print(f"转换失败 {input_path}: {str(e)}")
            return None

    def batch_convert_directory(self, input_dir, output_dir=None):
        """
        批量转换目录中的所有HEIC文件

        Args:
            input_dir: 包含HEIC文件的目录
            output_dir: 输出JPG文件的目录（可选）
        """
        input_dir = Path(input_dir)
        if output_dir:
            output_dir = Path(output_dir)
            output_dir.mkdir(parents=True, exist_ok=True)

        # 获取所有HEIC文件
        heic_files = list(input_dir.glob('*.HEIC')) + list(input_dir.glob('*.heic')) + \
            list(input_dir.glob('*.HIF')) + list(input_dir.glob('*.hif'))

        if not heic_files:
            print(f"在 {input_dir} 中没有找到HEIC文件")
            return

        print(f"找到 {len(heic_files)} 个HEIC文件")

        for heic_file in heic_files:
            if output_dir:
                output_path = output_dir / f"{heic_file.stem}.jpg"
            else:
                output_path = None
            self.convert_heic_to_jpg(str(heic_file), str(output_path) if output_path else None)

if __name__ == '__main__':
    app = wx.App()
    ex = HeicToJpgConverter(None)
    ex.Show()
    app.MainLoop()

